//Copyright (c) 2012, peter.ducai@gmail.com
//All rights reserved.
//
//Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following 
//conditions are met:
//
//Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
//Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer
//in the documentation and/or other materials provided with the distribution.
//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
//INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
//IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
//OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
//OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
//OF SUCH DAMAGE.
package com.daemonna.fluentlee_core.readers;

import com.daemonna.fluentlee_core.job.job;
import com.daemonna.fluentlee_core.job.suite;
import com.daemonna.fluentlee_core.pools.schedule_pool;
import java.io.IOException;
import java.text.DateFormat;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.*;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

/*
 * @author peter 'daemonna' ducai @author peter.ducai@gmail.com @author
 * http://code.google.com/p/fluentlee/
 */
public class schedule_reader {

    DocumentBuilderFactory domFactory = null;
    DocumentBuilder builder = null;
    DateFormat dateFormat;
    long gexec_time = 0;
    long exec_time = 0;
    long elaps_time = 0;
    boolean lock = false;

    /**
     * create xml reader and disable schema/dtd
     */
    public schedule_reader() {

        domFactory = DocumentBuilderFactory.newInstance();
        domFactory.setNamespaceAware(true); // never forget this!
        domFactory.setValidating(false);

        try {
            domFactory.setFeature("http://xml.org/sax/features/validation", false);
            domFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);
            domFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
            domFactory.setFeature("http://xml.org/sax/features/external-general-entities", false);
            domFactory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        } catch (Exception e1) {
            Logger.getLogger(settings_reader.class.getName()).log(Level.SEVERE, null, e1);
        }

    }

    /**
     * Read simple_schedule.xml and load data to data_pool
     */
    public void read_schedule(String schedule_name, int schedule_index) throws ParserConfigurationException, SAXException, XPathExpressionException, IOException, InterruptedException {
        System.out.println("READING SCHEDULE: schedules/" + schedule_name);

        //TODO if custom_schedule is set on cli

        builder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
        Document doc = builder.parse("schedules/" + schedule_name + ".schedule");
        XPathFactory factory = XPathFactory.newInstance();
        XPath xpath = factory.newXPath();
        XPathExpression expr = xpath.compile("//schedule/suite");
        Object result = expr.evaluate(doc, XPathConstants.NODESET);
        NodeList snode = (NodeList) result;


        //for all suites in current schedule, read their jobs
        for (int gg = 0; gg < snode.getLength(); gg++) {

            System.out.println("creating suite");
            schedule_pool.getInstance().scheds[schedule_index].suite_count++;
            schedule_pool.getInstance().scheds[schedule_index].suites[gg] = new suite();
            schedule_pool.getInstance().scheds[schedule_index].suites[gg].id = gg;
            schedule_pool.getInstance().scheds[schedule_index].suites[gg].name = snode.item(gg).getAttributes().getNamedItem("name").getTextContent();

            //System.out.println("SCHEDULE:"+schedule_index+" SUITE:"+gg);

            XPathFactory sfactory = XPathFactory.newInstance();
            XPath sxpath = sfactory.newXPath();
            XPathExpression sexpr = sxpath.compile("//schedule/suite[@name='" + schedule_pool.getInstance().scheds[schedule_index].suites[gg].name + "']/*");
            Object sresult = sexpr.evaluate(doc, XPathConstants.NODESET);
            NodeList node = (NodeList) sresult;

            for (int i = 0; i < node.getLength(); i++) {

                schedule_pool.getInstance().scheds[schedule_index].job_count++;

                schedule_pool.getInstance().scheds[schedule_index].suites[gg].job_count++;
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i] = new job();
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].status = job.jobstatus.INACTIVE;
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].id = i;
                //schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].chain_to[0] = Integer.getInteger(node.item(i).getAttributes().getNamedItem("chain_to").getTextContent());
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].name = node.item(i).getAttributes().getNamedItem("name").getTextContent();
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].command_value = node.item(i).getTextContent();
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].comment = node.item(i).getAttributes().getNamedItem("comment").getTextContent();
                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].suite_name = schedule_pool.getInstance().scheds[schedule_index].suites[gg].name;
                /*
                 * determine type of job
                 */
                switch (node.item(i).getNodeName()) {
                    case "run":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.RUN;
                        break;
                    case "sql":
                        /*
                         * write down also connector name
                         */
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.SQL;
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name1 = node.item(i).getAttributes().getNamedItem("connector").getTextContent();
                        if (node.item(i).getAttributes().getNamedItem("count_should_equal") != null) {
                                String cse = node.item(i).getAttributes().getNamedItem("count_should_equal").getTextContent();
                                schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].count_should_equal = Integer.parseInt(cse);
                        }
                        break;
                    case "sql_compare":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.SQL_COMPARE;
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name1 = node.item(i).getAttributes().getNamedItem("name").getTextContent();
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name2 = node.item(i).getAttributes().getNamedItem("name2").getTextContent();
                        break;
                    case "checksum":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.CHECKSUM;
                        //schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name1 = node.item(i).getAttributes().getNamedItem("name").getTextContent();
                        break;
                    case "crypto":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.CRYPTO;
                        //schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name1 = node.item(i).getAttributes().getNamedItem("name").getTextContent();
                        break;
                    case "ssh":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.SSH;
                        //ssh stuff
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].ssh_host = node.item(i).getAttributes().getNamedItem("host").getTextContent();
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].ssh_pass = node.item(i).getAttributes().getNamedItem("password").getTextContent();
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].ssh_port = 22;//Integer.getInteger(node.item(i).getAttributes().getNamedItem("port").getTextContent());
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].ssh_username = node.item(i).getAttributes().getNamedItem("user").getTextContent();
                        break;
                    case "maven_run":
                        schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].type = job.jobtype.MAVEN_RUN;
                        //schedule_pool.getInstance().scheds[schedule_index].suites[gg].jobs[i].con_name1 = node.item(i).getAttributes().getNamedItem("name").getTextContent();
                        break;
                }



            }

        }

    }
}
